package com.za.plugin.transfer.form;

import com.za.plugin.pojo.Content;
import com.za.plugin.util.StrUtil;

import java.util.List;

// 把 if() 转为 case-when-then-else-end ,支持 if() 函数嵌套
public class IfFormTransfer implements FormTransfer {
    @Override
    public boolean isSupport(String sql) {
        return clearSpace(sql).contains("if(");
    }

    private String clearSpace(String sql) {
        return sql.replaceAll("if\\s*\\(", "if(");
    }


    @Override
    public String transfer(String sql) {
        sql = clearSpace(sql);
        if (sql.contains("if(")) {
            sql = getTrans(sql);
        }
        return sql;
    }

    public String getTrans(String sql) {
        int idx = sql.indexOf("if(");
        while (idx >= 0) {
            StringBuilder sb = new StringBuilder();
            Content expectContent = StrUtil.getExpectContent(sql, idx + 2);
            assert expectContent != null;
            String expectStr = expectContent.getExpectStr();
            int end = expectContent.getEnd();

            List<String> segmentList = StrUtil.getSegment(expectStr, 0, expectStr.length());
            String whenStr = segmentList.get(0);
            // if() 函数里的 whenStr，trueStr，falseStr 都可能继续有 if() 函数，所以需要递归执行，
            // 要把所有的嵌套 if() 都变为嵌套的 case when。在分支选择判断的地方最容易出现嵌套，比如 if(),case when，而
            // 其他的普通函数则很少有嵌套，即使有，也很容易通过迭代的方式遍历出来，因为普通函数就只有一个执行分支，比如
            // date_format(date_format('2012-12-12 12:12:12','%Y-%m-%m'),'%Y'),要么执行成功，要么执行失败。
            if (whenStr.contains("if(")) {
                whenStr = "(" + getTrans(whenStr) + ")";
            }
            String trueStr = segmentList.get(1);

            if (trueStr.contains("if(")) {
                trueStr = "(" + getTrans(trueStr) + ")";
                //  if(num1 != null,num2 != null,num3) 的解决方法
            } else if (trueStr.contains("!=") && trueStr.split("!=")[1].trim().equalsIgnoreCase("null")) {
                String[] split = trueStr.split("!=");
                trueStr = "ifnull(" + split[0] + ",0)";
            }
            String falseStr = segmentList.get(2);
            if (falseStr.contains("if(")) {
                falseStr = "(" + getTrans(falseStr) + ")";
            }
            sql = sb.append(sql, 0, idx).append(" case when ").append(whenStr).append(" then ").append(trueStr).append(" else ")
                    .append(falseStr).append(" end ").append(sql.substring(end)).toString();
            idx = sql.indexOf("if(", idx + 3);
        }
        return sql;
    }
}
